package exercises.leetcode;

/**
 * <a href="https://leetcode-cn.com/problems/super-washing-machines/">
 * 517. 超级洗衣机</a>
 *
 * <p><span color="#87CEEB">描述:</span>
 * 假设有 n 台超级洗衣机放在同一排上。开始的时候，每台洗衣机内可能有一定量的衣服，也可能是空的。
 * <p>
 * 在每一步操作中，你可以选择任意 m (1 <= m <= n) 台洗衣机，与此同时将每台洗衣机的一件衣服送到相邻的一台洗衣机。
 * <p>
 * 给定一个整数数组 machines 代表从左至右每台洗衣机中的衣物数量，请给出能让所有洗衣机中剩下的衣物的数量相等的 最少的操作步数 。如果不能使每台洗衣机中衣物的数量相等，则返回 -1 。
 * <p>
 *  
 * <p>
 * 示例 1：
 * <p>
 * 输入：machines = [1,0,5]
 * 输出：3
 * 解释：
 * <p>
 * 第一步:    1     0 <-- 5    =>    1     1     4
 * <p>
 * 第二步:    1 <-- 1 <-- 4    =>    2     1     3
 * <p>
 * 第三步:    2     1 <-- 3    =>    2     2     2
 * <p>
 * 示例 2：
 * <p>
 * 输入：machines = [0,3,0]
 * 输出：2
 * 解释：
 * <p>
 * 第一步:    0 <-- 3     0    =>    1     2     0
 * <p>
 * 第二步:    1     2 --> 0    =>    1     1     1
 * <p>
 * 示例 3：
 * <p>
 * 输入：machines = [0,2,0]
 * 输出：-1
 * 解释：
 * 不可能让所有三个洗衣机同时剩下相同数量的衣物。
 *  
 * <p>
 * 提示：
 * <li>n == machines.length</li>
 * <li>1 <= n <= 104</li>
 * <li>0 <= machines[i] <= 105</li>
 *
 * @author or2
 * @date 2021年09月29日 时间: 11:51
 */
public class No517 {
    public int findMinMoves(int[] machines) {
        int length = machines.length;
        for (int i = 1; i < length; i++)
            machines[i] += machines[i - 1];

        int amount = machines[length - 1];
        if (amount % length != 0)
            return -1;

        /* 平均值 */
        int average = amount / length;
        /* 记录答案 */
        int res = Math.abs(average - machines[0]);
        /* 自该洗衣机起, 左边应有的数量 */
        int require = average;
        /* 查找最大偏移量 (边界特殊处理) */
        for (int i = 1, toLeft = -machines[0] + require; i < length; i++) {
            require += average;
            int toRight = machines[i] - require;
            /* 暂存 */
            int temp2Left = -toRight;
            /* 不能同时发 */
            if (toRight > 0 && toLeft > 0)
                toRight += toLeft;
            /* 从暂存中恢复 */
            toLeft = temp2Left;
            toRight = Math.abs(toRight);
            if (toRight > res)
                res = toRight;
        }
//System.gc();
        return res;
    }
}
